/* Test file for mpfr_set_str.

Copyright 2004-2021 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.

This file is part of the GNU MPFR Library.

The GNU MPFR Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

The GNU MPFR Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.

You should have received a copy of the GNU Lesser General Public License
along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */

#include "mpfr-test.h"

/* The implicit \0 is useless, but we do not write num_to_text[62] otherwise
   g++ complains. */
static const char num_to_text36[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char num_to_text62[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  "abcdefghijklmnopqrstuvwxyz";

static void
check_special (void)
{
  mpfr_t x, y;
  int i, res;
  char *s;

  mpfr_init (x);
  mpfr_init (y);

  /* Check dummy case */
  res = mpfr_strtofr (x, "1234567.89E1", NULL, 10, MPFR_RNDN);
  mpfr_set_str (y, "1234567.89E1", 10, MPFR_RNDN);
  if (mpfr_cmp (x, y))
    {
      printf ("Results differ between strtofr and set_str.\n"
              " set_str gives: ");
      mpfr_dump (y);
      printf (" strtofr gives: ");
      mpfr_dump (x);
      exit (1);
    }

  /* Check NAN  */
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NaN", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || *s != 0)
    {
      printf ("Error for setting NAN (1)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "+NaN", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || *s != 0)
    {
      printf ("Error for setting +NAN (1)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, " -NaN", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || *s != 0)
    {
      printf ("Error for setting -NAN (1)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "@nAn@xx", &s, 16, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "xx") )
    {
      printf ("Error for setting NAN (2)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NAN(abcdEDF__1256)Hello", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "Hello") )
    {
      printf ("Error for setting NAN (3)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NAN(abcdEDF)__1256)Hello", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "__1256)Hello") )
    {
      printf ("Error for setting NAN (4)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NAN(abc%dEDF)__1256)Hello", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "(abc%dEDF)__1256)Hello") )
    {
      printf ("Error for setting NAN (5)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NAN((abc))", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "((abc))") )
    {
      printf ("Error for setting NAN (6)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */
  res = mpfr_strtofr (x, "NAN()foo", &s, 10, MPFR_RNDN);
  if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "foo") )
    {
      printf ("Error for setting NAN (7)\n");
      exit (1);
    }

  /* Check infinity */
  for (i = 0; i <= 0xff; i++)
    {
      char t[11] = "+@INFINITY";  /* not char *: this will be modified. */
      char *p;
      int base, j;

      /* Test all the case variants, assuming ASCII or similar.
         The first letters are changed first, so that at i = 8,
         the 2^3 = 8 "INF" case variants have been tested, and
         they don't need to be tested again for i > 8. */
      for (j = 0; j < 8; j++)
        if ((i >> j) % 2 != 0)
          t[j+2] += 'a' - 'A';

      /* Test "INFINITY", "+INFINITY", "-INFINITY",
              "INF", "+INF", "-INF",
              "@INF@", "+@INF@", "-@INF@",
         up to case changes. */
      for (j = 0; j < 9; j++)
        {
          if (j == 3)
            {
              /* At i = 8, we have tested all the "INF" case variants. */
              if (i >= 8)
                break;
              t[5] = '\0';
            }
          if (j == 6)
            {
              t[1] = '@';
              t[5] = '@';
              t[6] = '\0';
            }
          if (j % 3 == 1)
            t[j != 7] = '+';
          if (j % 3 == 2)
            t[j != 8] = '-';
          p = t + (j % 3 == 0) + (j < 6);
          base = randlimb () % (j < 6 ? 17 : 63);
          if (base == 1)
            base = 0;
          res = mpfr_strtofr (x, p, &s, base, MPFR_RNDN);
          if (res != 0 || !mpfr_inf_p (x) || *s != 0 ||
              (j % 3 != 2 ? MPFR_IS_NEG (x) : MPFR_IS_POS (x)))
            {
              printf ("Error for setting \"%s\" in base %d\n s=\"%s\"\n x=",
                      p, base, s);
              mpfr_dump (x);
              exit (1);
            }
        }
    }
  res = mpfr_strtofr (x, "INFANITY", &s, 8, MPFR_RNDN);
  if (res != 0 || !mpfr_inf_p (x) || strcmp(s, "ANITY"))
    {
      printf ("Error for setting INFINITY (2)\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  res = mpfr_strtofr (x, "@INF@*2", &s, 11, MPFR_RNDN);
  if (res != 0 || !mpfr_inf_p (x) || strcmp(s, "*2"))
    {
      printf ("Error for setting INFINITY (3)\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }

  /* Check Zero */
  res = mpfr_strtofr (x, " 00000", &s, 11, MPFR_RNDN);
  if (res != 0 || !mpfr_zero_p (x) || s[0] != 0)
    {
      printf ("Error for setting ZERO (1)\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }

  /* Check base 62 */
  res = mpfr_strtofr (x, "A", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 10))
    {
      printf ("Error for setting 'A' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "a", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 36))
    {
      printf ("Error for setting 'a' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "Z", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 35))
    {
      printf ("Error for setting 'Z' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "z", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 61))
    {
      printf ("Error for setting 'z' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "ZA", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 2180))
    {
      printf ("Error for setting 'ZA' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "za", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 3818))
    {
      printf ("Error for setting 'za' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "aZ", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 2267))
    {
      printf ("Error for setting 'aZ' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "Az", NULL, 62, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 681))
    {
      printf ("Error for setting 'Az' in base 62\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }

  /* Check base 60 */
  res = mpfr_strtofr (x, "Aa", NULL, 60, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 636))
    {
      printf ("Error for setting 'Aa' in base 60\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }
  res = mpfr_strtofr (x, "Zz", &s, 60, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 35) || strcmp(s, "z") )
    {
      printf ("Error for setting 'Zz' in base 60\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }

  /* Check base 61 */
  res = mpfr_strtofr (x, "z", &s, 61, MPFR_RNDN);
  if (res != 0 || mpfr_cmp_ui (x, 0) || strcmp(s, "z") )
    {
      printf ("Error for setting 'z' in base 61\n x=");
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
      putchar ('\n');
      exit (1);
    }

  mpfr_clear (x);
  mpfr_clear (y);
}

/* The following RefTable has been generated by this following code */
#if 0
#define MAX_NUM 100

int randomab (int a, int b)
{
  return a + rand () % (b-a);
}

int
main (void)
{
  int i, base;
  mpfr_t x;
  mpfr_prec_t p;
  mpfr_exp_t e;

  mpfr_init (x);
  printf ("struct dymmy_test { \n"
          " mpfr_prec_t prec; \n"
          " int base; \n"
          " const char *str; \n"
          " const char *binstr; \n"
          " } RefTable[] = { \n");
  for (i = 0 ; i < MAX_NUM ; i++)
    {
      p = randomab(2, 180);
      base = randomab (2, 30);
      e = randomab (-1<<15, 1<<15);
      mpfr_set_prec (x, p);
      mpfr_urandomb (x, RANDS);
      mpfr_mul_2si (x, x, e, MPFR_RNDN);
      printf("{%lu, %d,\n\"", p, base);
      mpfr_out_str (stdout, base, p, x, MPFR_RNDN);
      printf ("\",\n\"");
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
      printf ("\"}%c\n", i == MAX_NUM-1 ? ' ' : ',' );
    }
  printf("};\n");
  mpfr_clear (x);
}
#endif

static struct dymmy_test {
 mpfr_prec_t prec;
 int base;
 const char *str;
 const char *binstr;
 } RefTable[] = {
{39, 20,
"1.1c9jeh9jg12d8iiggf26b8ce2cig24agai51d9@1445",
"1.00111010111010001110110001101011101011e6245"},
{119, 3,
"1.2210112120221020220021000020101121120011021202212101222000011110211211122222001001221110102220122021121021101010120101e-5655",
"1.1111101110011110001101011100011000011100001011011100010011010010001000000111001010000001110111010100011000110010000000e-8963"},
{166, 18,
"3.ecg67g31434b74d8hhbe2dbbb46g9546cae72cae0cfghfh00ed7gebe9ca63b47h08bgbdeb880a76dea12he31e1ccd67e9dh22a911b46h517b745169b2g43egg2e4eah820cdb2132d6a4f9c63505dd4a0dafbc@-5946",
"1.011110010000110011111011111100110110010110000010100001101111111000010000011111110101100000010110011001100000010001100101000001101000010010001011001011000110100011001e-24793"},
{139, 4,
"1.020302230021023320300300101212330121100031233000032101123133120221012000000000000000000000000000000000000000000000000000000000000000000000e11221",
"1.001000110010101100001001001011111000110000110000010001100110111100011001010000001101101111000000001110010001011011011111011000101001000110e22442"},
{126, 13,
"4.a3cb351c6c548a0475218519514c6c54366681447019ac70a387862c39c86546ab27608c9c2863328860aa2464288070a76c0773882728c5213a335289259@2897",
"1.01011010000001110001100001101111100111011010010111000011000101111011000100001010010100110111101001001001000000011100010000000e10722"},
{6, 26,
"1.j79f6@-1593",
"1.00000e-7487"},
{26, 18,
"3.5e99682hh310aa89hb2fb4h88@-5704",
"1.0110010100010101000101100e-23784"},
{12, 21,
"4.j7f3e2ccdfa@-3524",
"1.10110101011e-15477"},
{38, 28,
"o.agr0m367b9bmm76rplg7b53qlj7f02g717cab@6452",
"1.1001010011101100110100111000111010001e31021"},
{75, 17,
"4.00abd9gc99902e1cae2caa7647gcc029g01370e96d3f8e9g02f814d3ge5faa29d40b9db470@5487",
"1.11100000110101010111101001110001001010111111010100000100001010100111011101e22429"},
{91, 16,
"1.0a812a627160014a3bda1f00000000000000000000000000000000000000000000000000000000000000000000@7897",
"1.000010101000000100101010011000100111000101100000000000010100101000111011110110100001111100e31588"},
{154, 19,
"1.989279dda02a8ic15e936ahig3c695f6059a3i01b7d1ge6a418bf84gd87e36061hb2bi62ciagcgb9226fafea41d2ig1e2f0a10ea3i40d6dahf598bdbh372bdf5901gh276866804ah53b6338bi@5285",
"1.110101101101101111110010001011110001100000010100011101101001000100110100000011110111000011011101011110010100110101011011111100101101001100000101101000010e22450"},
{53, 2,
"1.0100010111100111001010000100011011111011011100110111e-20319",
"1.0100010111100111001010000100011011111011011100110111e-20319"},
{76, 3,
"2.101212121100222100012112101120011222102000021110201110000202111122221100001e1511",
"1.000110101010111000011001011111110000001001101001011011111110111111010000111e2396"},
{31, 9,
"1.171774371505084376877631528681e3258",
"1.110101101011111011111000110011e10327"},
{175, 8,
"4.506242760242070533035566017365410474451421355546570157251400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3483",
"1.001010001100101000101111100000101000100001110001010110110000111011011101100000011110111101011000010001001111001001010011000100010111011011011001101011110000011011110101010011e10451"},
{103, 24,
"8.0hmlm3g183cj358fn4bimn5bie1l89k95m647474mm8jg5kh1c011gi0m7de9j7b48c595g1bki4n32kll7b882eg7klgga0h0gf11@4510",
"1.001000110101001101011010101001111010110100010100110101010101110000001011001101110110010111000101010111e20681"},
{12, 9,
"3.00221080453e2479",
"1.11000111010e7859"},
{86, 11,
"6.873680186953174a274754118026423965415553a088387303452447389287133a0956111602a5a085446@5035",
"1.0000000000110100010110000111010001010100101011000100101010010011101010000110011110001e17421"},
{68, 10,
"6.1617378719016284192718392572980535262609909598793237475124371481233e481",
"1.0110001011000101110010111101100101111110001100001011110011001101111e1600"},
{11, 15,
"5.ab10c18d45@907",
"1.0000101111e3546"},
{77, 26,
"6.e6kl84g6h30o3nfnj7fjjff4n1ee6e5iop76gabj23e7hgan9o6724domc7bp4hdll95g817519f@5114",
"1.1011000101111111111110011011101100000100101000001001100000001011010001001000e24040"},
{28, 27,
"d.odiqp9kgh84o8d2aoqg4c21hemi@3566",
"1.101001111001111111110011110e16959"},
{45, 14,
"7.cddc6295a576980adbc8c16111d6301bad3146a1143c@-6227",
"1.10000000110011000000101100110001011100010111e-23706"},
{54, 19,
"1.b6e67i2124hfga2g819g1d6527g2b603eg3cd8hhca9gecig8geg1@4248",
"1.11010100100010101101110110010100000010111010010101110e18045"},
{49, 20,
"1.jj68bj6idadg44figi10d2ji99g6ddi6c6ich96a5h86i529@-3149",
"1.001011111101100100001010001000011100000000101110e-13609"},
{171, 16,
"6.22cf0e566d8ff11359d70bd9200065cfd72600b12e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@5602",
"1.10001000101100111100001110010101100110110110001111111100010001001101011001110101110000101111011001001000000000000001100101110011111101011100100110000000001011000100101110e22410"},
{144, 14,
"1.425d9709b4c125651ab88bb1a0370c14270d067a9a74a612dad48d5c025531c175c1b905201d0d9773aa686c8249db9c0b841b10821791c02baa2525a4aa7571850439c2cc965cd@-3351",
"1.11100111110001001101010111010000101010011000111001101011000001011110101110011011100100111001101101111011001001101011001101001011011101101111011e-12759"},
{166, 6,
"3.324252232403440543134003140400220120040245215204322153511143504542403430152410543444455151104314552352030352125540101550151410414122051500201022252511512332523431554e8340",
"1.010101111101111101001001110010111110010000001111010101100110011011010110011001001100001111010101100000010111011111101110110111101110010001110001111000001010001111000e21560"},
{141, 24,
"2.i3c88lkm2958l9ncb9f85kk35namjli84clek5j6jjkli82kb9m4e4i2g39me63db2094cif80gcba8ie6l15ia0d667kn9i1f77bdak599e1ach0j05cdn8kf6c6kfd82j2k6hj2c4d@4281",
"1.10011100001010110111001000000000101011100010101011001010001101110100110111011000111101000001111101100000110100100010101011001100100011001011e19629"},
{84, 6,
"2.41022133512503223022555143021524424430350133500020112434301542311050052304150111243e982",
"1.11010001111111001010011100011000011100100111111010001111010010101001001000011100001e2539"},
{56, 9,
"1.5305472255016741401411184703518332515066156086511016413e2936",
"1.0111110010001101000000110101110000110101001011001100111e9307"},
{18, 8,
"3.63542400000000000e-599",
"1.11100111011000101e-1796"},
{111, 13,
"8.b693ac7a24679b98708a0057a6202c867bc146740ab1971b380756a24c99804b63436419239ba0510030b819933771a636c57c5747b883@-6160",
"1.01011011111110100101110010100100000110000011011101001110010110000011101110111111010111000011011101101001100100e-22792"},
{162, 16,
"4.f2abe958a313566adbf3169e55cdcff3785dbd5c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@382",
"1.00111100101010101111101001010110001010001100010011010101100110101011011011111100110001011010011110010101011100110111001111111100110111100001011101101111010101110e1530"},
{117, 23,
"2.4b6kk3ag3if217ih1hggkk69bmcecfil1cd38dijh35j8e6ckhd335a4gj7l05bedk19473i8449b1ajc3jd3ka95eceheh72lh2jh17jamlm1142gll@-3628",
"1.10010010001010001110011000010000011111011101111100110101100100101111101110010011101001111010100010001111110100101111e-16411"},
{179, 2,
"1.1101101011111010101000110101010101101110001011011010101001110111011010011110001000000110101100010010001110010110011000000110001011111001011110100011101000110001001000110100100110e14203",
"1.1101101011111010101000110101010101101110001011011010101001110111011010011110001000000110101100010010001110010110011000000110001011111001011110100011101000110001001000110100100110e14203"},
{18, 27,
"4.ll743n2f654gh3154@-6039",
"1.01101001111010011e-28713"},
{178, 15,
"1.e5443105cad2d014b700c42aa3de854c4b95322420695d07db3564ec07473da83bde123b74c794139265a838ebeca745ad3dc97d7c356271ca935ea8e83306562c2a8edc6e886c1b6b2d3e17038379c33826526770985c068@821",
"1.011100001000101100111111111111000100110111110011101010001111011001111101111001010011100100100101100011101001000000101001010100011111001011001010011101101001000111111010101101011e3208"},
{161, 22,
"2.46ikji624bg042877h8g2jdki4ece6ede62841j7li843a4becdkkii86c54192jkefehikkb3kcb26ij1b3k9agfbb07dih88d6ej0ee0d63i8hedc7f0g0i9g7jf9gf6423j70h421bg5hf2bja9j0a432lb10@-5125",
"1.0111011000111110000010011100001100100110001011101001011110111010100000011100000010011101011100101100111100110000001101010101011110100011101111001011001111100000e-22854"},
{62, 19,
"7.bgd1g0886a6c3a9ee67cc7g3bgf718i98d90788idi5587358e660iffc0ic6@3257",
"1.0101100100001110000100010110100100000111110001111001011110100e13838"},
{127, 19,
"1.413bgf99eidba75ged25f7187080bce3h7ebdeghea4ig6c79g94di7b42a3e4cdi4ic6a53i71d2e4hdbe50ih0a0egf2fi469732131ig6g496bf7h8g3c86ie7h@-4465",
"1.001101111000011011100010010010010110111001001001110011110101111111000001110101111110001110010000110011111101000011000101111101e-18967"},
{17, 21,
"4.7d5b70gh4k0gj4fj@-116",
"1.1000100010000110e-508"},
{141, 13,
"2.2b4988c5cb57072a6a1a9c42224794a1cbc175a9bc673bb28aa045c3182b9396ca8bb8590969672b0239608a845a2c35c08908a58c2a83748c89241a6561422c7cc4866c8454@4358",
"1.10010110101000001000001001111001000100111110100010100110111011111011010010101000110101110000111100010000101101000110000000000001111110110011e16127"},
{39, 7,
"3.00350342452505221136410100232265245244e202",
"1.10011000111110011010100110101101010010e568"},
{119, 24,
"5.2aene587kc2d9a55mm8clhn4dn0a551de58b1fcli8e8hf1jlm7i0376dl5fhb2k8acka03077mnbn9d4dmi0641dce871c81g2b3ge76m3kngm4a9g5gh@-892",
"1.0111101010010100001001111110000000100101110010010111111100100101100001010010100110111000101100101010111000101111000010e-4088"},
{41, 14,
"5.c3dc5c49373d0c0075624931133022185bd08b16@-5294",
"1.0101011000010111111111000010100110011111e-20154"},
{41, 6,
"3.2411143454422033245255450304104450302500e2250",
"1.1110111101010101001001100000100011110111e5817"},
{17, 13,
"3.65789aa26aa273b1@-4490",
"1.1100011101010111e-16614"},
{10, 26,
"1.5p4hag1fl@6017",
"1.110010111e28282"},
{130, 11,
"2.606a72601843700427667823172635a47055021a0a68a99326875195a179483948407aa13726244552332114a1784aaa7239956521604460876871a65708458aa@-6285",
"1.110001001110111110110111000010101000110010011110010101100100001000101011010010000001000101000110111111110101000100000111100010100e-21742"},
{29, 20,
"j.4356d9b7i38i955jjj1j442501bj@163",
"1.1010101011110011100000100100e708"},
{140, 21,
"9.2f5k7aid6bj2b2g5bff29i73hk3a8d8g0i7ifa07hkb79g4hd3c7j6g4hjj2jbhai01gkje3h9g3gj3i34f0194kaed32iea9dcgcj8h7i1khdkf965c1ak97gf3h03fcab3ggi03fa@4864",
"1.0101011100011101000110101001010011111111010011000111111111100000011011100111010001100101100110001110001001100101001100110000011110100101101e21367"},
{133, 13,
"2.3721a9107307a71c75c07c83b70a25a9853619030b5bcb55101ca5c2060bca46c331b92b33aa957c3ac7c817335287c6917999c38c3806b6b5919623023ac52063bb@6602",
"1.011001101111100001100100110100010100010011100010111110110100100000000010011101001011000100000110011011101001010010011110111100010010e24431"},
{118, 2,
"1.001010111011011000100010001110111000001100101000101101010001110110000111101110111011011101111100110010000101001001001e18960",
"1.001010111011011000100010001110111000001100101000101101010001110110000111101110111011011101111100110010000101001001001e18960"},
{102, 23,
"l.26lhk42clcm9g940eihakhi32gb3331lld488cf1j4f73ge051bfl8gcmcg78gkjc2iibjf752eag0dee6dafa97k79jlh11j3270@-2160",
"1.01101011011000100101110111110001011000101101011001011111001101000110111010000010011111101110101100010e-9767"},
{156, 18,
"b.eb927dd4g48abee3cc2begehb9c3b8h83cae152db850ac2f3g816d6787825122c8h3aa3g8023h23000a8hg61065b3e367ac59ca373067730f96dd0d3b73b3c43fef91750b333gd497b8ce9228e7@5504",
"1.11000110111100011101100011001001110011101100011111010100101110010010010011111001100000011010011111111011001011111010001001011001110001100001101000000110000e22954"},
{158, 5,
"3.0112043214104344433122444210142004032004444213123303302023242414000243311324332203224340334422234000104132020124210141322013240010134130441413233111204013422e-10468",
"1.1001011000111111110100100101110011100001110100101001101110011001101001101011010010111010111111101010100011100010101100110111011101000110110100000111001100011e-24305"},
{7, 9,
"2.141540e-146",
"1.001111e-462"},
{111, 5,
"3.21233234110011204313222402442032333320324004133424222041314021020411320312421014434003440431230413141402230403e7641",
"1.10010000000101010000101010101011011010000100010010010000010110001111000111111111000110111001100101101110101101e17743"},
{76, 13,
"7.1c0861453a4ac156b6119ba7548251b5cb00b7c409c2bb8138214676468c9949676226013c1@4639",
"1.001000011000000011101101101010100010010001010111100110010101111110110010111e17169"},
{6, 25,
"c.aj660@-6978",
"1.11000e-32402"},
{156, 3,
"2.22101000022222000012110122210202211110020121210120112102122121111210000211020001020201202200011021211102012110220222110022001121011022011202000110120021012e-14744",
"1.11010001111000101111110000010011001101000100010010110011100100110001100111011101011111111100011111001100001111100101100000001000001100000000010010001011101e-23368"},
{7, 23,
"1.4hclk2@2148",
"1.110110e9716"},
{69, 11,
"2.77684920493191632416690544493465617a187218365952a6740034288687745a26@3263",
"1.01111000111000001111001110000110000110001111110011101100101111011100e11289"},
{146, 21,
"3.agg4d0dj636d526d4i8643ch5jee4ge2c3i46k121857dbedagd98cjifaf0fgc09ca739g2fkfbfh06i687kic2kb8c7i48gda57bb6d9bh81eh49h0d8e3i7ad2kgb1ek86b86g3589k27d@3562",
"1.0010111111111100101010101010001100110101010011011100001110111000101101001110001110010100000001010001000111010000010011110100010010101100101000001e15647"},
{20, 3,
"1.2000000021102111102e-16642",
"1.1011101011111110000e-26377"},
{68, 13,
"1.a43205b2164676727806614acc0398925569c3962a3ba419881a5c63b651aa3ab46@-618",
"1.1111011000001110010100111000110010110110011001110001100101011111000e-2287"},
{129, 4,
"2.22033002012102010122130132103000303000120122313322000222121000300000000000000000000000000000000000000000000000000000000000000000e13222",
"1.01010001111000010000110010010000100011010011100011110010011000000110011000000011000011010110111111010000000101010011001000000110e26445"},
{22, 6,
"1.420033001013011530142e11704",
"1.001000110010110110001e30255"},
{108, 6,
"1.03345424443433104422104400512453214240453335230205104304115343030341144544051005432030344054100542125304500e7375",
"1.00101101110001011101101111000010101011101000001111001110001101100000111100010101010101101100011110111010000e19064"},
{91, 27,
"2.ao077kf8oqoihn5pm6f5eqdcgnd2132d7p6n7di8ep82a1a9be99pm36g1emacbenaeiqphpgpdjhmm9ke3pn4pdea@-5482",
"1.111101100001000011101010001000000111000100100111110010101101110001101101101101101010111110e-26066"},
{96, 9,
"8.25805186310703506315505842015248775712246416686874260383701323213202658278523870037877823670166e-8134",
"1.11010111111000011100111001011010001110010001011101011101110101000101100100100010110011001010000e-25782"},
{161, 16,
"7.3a7627c1e42ef738698e292f0b81728c4b14fe8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@-3342",
"1.1100111010011101100010011111000001111001000010111011110111001110000110100110001110001010010010111100001011100000010111001010001100010010110001010011111110100011e-13366"},
{90, 3,
"2.10212200011211012002002221112120210222002020100202111000211012122020011102022112222021001e-3447",
"1.11100010111011011000101111110001000101000111110001100001010111101101011011110001000010001e-5463"},
{100, 27,
"a.f81hjjakdnc021op6ffh530ec8ige6n2fqc8f8j7ia7qelebgqkm4ic5ohh652hq1kgpag6pp0ldin6ce1fg6mj34077f5qc5oe@6576",
"1.011101001010010011110001100011111111010001110110100100101001010000101011101011110010010011111100000e31271"},
{152, 16,
"e.37ac48a0303f903c9d20883eddea4300d1190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@-1388",
"1.1100011011110101100010010001010000000110000001111111001000000111100100111010010000010001000001111101101110111101010010000110000000011010001000110010000e-5549"},
{106, 20,
"1.3g2h7i2776d50gjibi937f8cdci3idecdeh3j2gba0j8d1ghgg3eg609ji55h5g7jeai1bii3a4f9jhjfij6jd1g3cg0f6024e252gc3e@6422",
"1.100110000101011010100111100110000000100101000110110011010010000101000100110010001110011110111100010000111e27755"},
{23, 17,
"9.f72e724454d1g0f60g93g6@-6563",
"1.0011100011110110010001e-26823"},
{98, 6,
"1.2444223304453415235424343034030405514010421403514410005234221430055051205523402412055242134042045e-8535",
"1.1101110011010001101001001111100101111010100111001011110001000010100101101110011011101100000111011e-22063"},
{4, 18,
"1.gec@-6711",
"1.100e-27984"},
{69, 24,
"8.d45gdfnhkhb7a20nj96dnggic83imhjne0cceldechn1m4e9fbd9db0ablngjf9n7810@6975",
"1.00100111111100101100110011110110110000110110110010100101011111000100e31983"},
{122, 8,
"4.0227760456667717717077553523466457265600000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1767",
"1.0000001001011111111000010010111011011011111100111111100111100011111110110101110101001110011011010010111101011010111000000e-5299"},
{144, 23,
"8.b01c48dg20bek9a5k376clc501aecg92bdjaeji2dm9230i7j3k36jm50b0c5a0753i2b18534cji34bcl2li033cc534m52k2gbegc25a5g30lf4calag58026i5d7li61jg9digj5ceb1@-4456",
"1.00010000110011010111011011110111001101111001010110001101011100100101101110110000010011011111100000100110001001001111111011010110000000001111110e-20154"},
{111, 4,
"2.23100111310122202021232133233012212012232222323230133100000000000000000000000000000000000000000000000000000000e-10458",
"1.01011010000010101110100011010100010001001101110011111101111000110100110000110101110101010111011101100011111010e-20915"},
{117, 10,
"1.61207328685870427963864999744776917701013812304254540861834226053316419217753608451422967376154318603744156166920074e-6440",
"1.01100011000100111001100010000000110010100001001011111010100001101111100100101100111010100011101110001010011010010010e-21393"},
{106, 16,
"1.dd30a1d24091263243ca1c144f0000000000000000000000000000000000000000000000000000000000000000000000000000000@354",
"1.110111010011000010100001110100100100000010010001001001100011001001000011110010100001110000010100010011110e1416"},
{77, 14,
"4.90d6913ba57b149d8d85a58c311b4d537c10bd7d3c10d69c62bc08d32269760126a58115a105@-7311",
"1.1001000000111100000111001001011000110101001111100001100111010100010000011111e-27834"},
{8, 4,
"3.2230000e15197",
"1.1101011e30395"},
{81, 24,
"1.84ni25h558abmhg2dk7bl2jbbmkf4i8i2bemc5cgmk9jf301c00k24271m9h7mgm4301be1lnldn4364@2573",
"1.01110010011000110110100101011001011111101111101100010110101101011101100001000010e11797"},
{94, 2,
"1.010010010101111001001011111111100100011110110100010001101111111100100101101100110101001011111e32427",
"1.010010010101111001001011111111100100011110110100010001101111111100100101101100110101001011111e32427"},
{77, 21,
"1.87e4k9df85g50ead6fcj4h86820ikdjdjg93d90ca406g470hhkh7ciaba1aggg753g36553ebh5@2538",
"1.0010001100011000111010000010011001010011000000100101010001100000111101000111e11148"},
{80, 17,
"1.923gga999230g94fce02efg753ce001045a35e0264c9c2cb17850e32484fc3526dcg38ed874g5f2@3392",
"1.0011100111101001001101111001110100001100111110011110110001100110101010111001110e13865"},
{99, 7,
"4.53646362336126606650465342500160461331562113222506144210636341332436342025203333264316511653025011e-5540",
"1.01101101111001001100001101101101010011001001100110111000010000101000011001001001101000011101011001e-15551"},
{119, 20,
"1.c8966iabcf4de94ad15f9e83j407i3he7fch54h5jh0g5d74e06c057gg72a107didj8d1j8geibbfec5j36c3fgd5e12edjb9g10j7c9i03f33hi80ce0@7153",
"1.0101110101100011110001001110100110011000100000001001000110111110011111100011111010011101011111101101010011110111110100e30915"},
{93, 13,
"2.c749cb562c3a758b1a21a650666a4c6c53c76ca58a1a75a0358c9ac3866887972b3551a03aa6c150856531258508@193",
"1.10101111101001011010111101100100111110011111010110111101100100010011001001100011110100111110e715"},
{145, 14,
"1.c61614b64261d22c62cb9d16163ca4d144ac23351b708506b3b610b1b67b764ca974448d7a2c6515a6bc97503d4b2a530c75b2b677a464c6629c69b6c3d7860d7749b4b653c434d5@2050",
"1.111111100001101111100011001111100010010000101000011110000001110100111001011010100001001010111111010001111101000110011000011101110110001001100101e7805"},
{159, 23,
"4.bj9l07l0215e7l6lf1dkf62i056l37jaa0gdih717656f1kk1a77883jf99jg31le43em76bmcg4lddl782ihkla0m392886d8lm67d6c3a1l4j12kg0l1k52ee77lmk0gech11g8jeei680k85bi460c7el17@-1539",
"1.01010100110100100101100001011100000001100011110001001101000010000001000010000110000110010001110100001101011101101001001101101111001101101111101001010010010100e-6960"},
{24, 25,
"g.m749al09kflg5b42jnn4a7b@-2820",
"1.01010010101011010111011e-13092"},
{88, 18,
"3.5ed0gad0bhhb7aa9ge2ad1dhcg6833f3e068936hghf23gd2aa69f13539f15hfce50aa64achfee49bfg7249g@-4058",
"1.001000010110011011000101100000101111101001100011101101001111110111000010010110010001100e-16920"}
};

static void
check_reftable (void)
{
  int i, base;
  mpfr_t x, y;
  mpfr_prec_t p;
  char *s;

  mpfr_init2 (x, 200);
  mpfr_init2 (y, 200);
  for (i = 0 ; i < numberof (RefTable) ; i++)
    {
      base = RefTable[i].base;
      p    = RefTable[i].prec;
      mpfr_set_prec (x, p);
      mpfr_set_prec (y, p);
      mpfr_set_str_binary (x, RefTable[i].binstr);
      mpfr_strtofr (y, RefTable[i].str, &s, base, MPFR_RNDN);
      if (s == NULL || *s != 0)
        {
          printf ("strtofr didn't parse entire input for i=%d:\n"
                  " Str=%s", i, RefTable[i].str);
          exit (1);
        }
      if (mpfr_cmp (x, y))
        {
          printf ("Results differ between strtofr and set_binary for i=%d:\n"
                  " Set binary gives: ", i);
          mpfr_dump (x);
          printf (" strtofr    gives: ");
          mpfr_dump (y);
          printf (" setstr     gives: ");
          mpfr_set_str (x, RefTable[i].str, base, MPFR_RNDN);
          mpfr_dump (x);
          mpfr_set_prec (x, 2*p);
          mpfr_set_str (x, RefTable[i].str, base, MPFR_RNDN);
          printf (" setstr ++  gives: ");
          mpfr_dump (x);
          exit (1);
        }
    }
  mpfr_clear (y);
  mpfr_clear (x);
}

static void
check_parse (void)
{
  mpfr_t x;
  char *s;
  int res;

  mpfr_init (x);

  /* Invalid data */
  mpfr_set_si (x, -1, MPFR_RNDN);
  res = mpfr_strtofr (x, "  invalid", NULL, 10, MPFR_RNDN);
  if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x))
    {
      printf ("Failed parsing '  invalid' (1)\n X=");
      mpfr_dump (x);
      exit (1);
    }
  MPFR_ASSERTN (res == 0);
  mpfr_set_si (x, -1, MPFR_RNDN);
  res = mpfr_strtofr (x, "  invalid", &s, 0, MPFR_RNDN);
  if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x) || strcmp (s, "  invalid"))
    {
      printf ("Failed parsing '  invalid' (2)\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  MPFR_ASSERTN (res == 0);
  /* Check if it stops correctly */
  mpfr_strtofr (x, "15*x", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 15) || strcmp (s, "*x"))
    {
      printf ("Failed parsing '15*x'\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  /* Check for leading spaces */
  mpfr_strtofr (x, "  1.5E-10 *x^2", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "1.5E-10") || strcmp (s, " *x^2"))
    {
      printf ("Failed parsing '1.5E-10*x^2'\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  /* Check for leading sign */
  mpfr_strtofr (x, "  +17.5E-42E ", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "17.5E-42") || strcmp (s, "E "))
    {
      printf ("Failed parsing '+17.5E-42E '\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-17.5E+42E\n", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "-17.5E42") || strcmp (s, "E\n"))
    {
      printf ("Failed parsing '-17.5E+42\\n'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* P form */
  mpfr_strtofr (x, "0x42P17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0x42P17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0X42p17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-0x42p17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "42p17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '42p17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42P17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-42P17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "0b1001P17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0b1001P17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0B1001p17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-0B1001p17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "1001p17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '1001p17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-1001P17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-1001P17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for auto-detection of the base */
  mpfr_strtofr (x, "+0x42P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "42P17", 16, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42E17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-42E17", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-42E17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-42", 10, MPFR_RNDN) || strcmp (s, "P17"))
    {
      printf ("Failed parsing '-42P17' (base = 0)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, " 0b0101.011@42", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, " 0b0101.011P42", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "+0x42@17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "4.2@18", 16, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }


  /* Check for space inside the mantissa */
  mpfr_strtofr (x, "+0x4 2@17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 4) || strcmp(s," 2@17"))
    {
      printf ("Failed parsing '+0x4 2@17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "+0x42 P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0x42) || strcmp(s," P17"))
    {
      printf ("Failed parsing '+0x42 P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Space between mantissa and exponent */
  mpfr_strtofr (x, " -0b0101P 17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -5) || strcmp(s,"P 17"))
    {
      printf ("Failed parsing '-0b0101P 17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for Invalid exponent. */
  mpfr_strtofr (x, " -0b0101PF17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -5) || strcmp(s,"PF17"))
    {
      printf ("Failed parsing '-0b0101PF17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* At least one digit in the mantissa. */
  mpfr_strtofr (x, " .E10", &s, 0, MPFR_RNDN);
  if (strcmp(s," .E10"))
    {
      printf ("Failed parsing ' .E10'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check 2 '.': 2.3.4   */
  mpfr_strtofr (x, "-1.2.3E4", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "-1.2") || strcmp(s,".3E4"))
    {
      printf ("Failed parsing '-1.2.3E4'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for 0x and 0b */
  mpfr_strtofr (x, "  0xG", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"xG"))
    {
      printf ("Failed parsing '  0xG'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "  0b2", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"b2"))
    {
      printf ("Failed parsing '  0b2'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0x.23@2Z33", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -0x23) || strcmp(s,"Z33"))
    {
      printf ("Failed parsing '-0x.23@2Z33'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "  0x", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"x"))
    {
      printf ("Failed parsing '  0x'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }

  mpfr_clear (x);
}

static void
check_overflow (void)
{
  mpfr_t x;
  char *s;

  mpfr_init (x);

  /* Huge overflow */
  mpfr_strtofr (x, "123456789E2147483646", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check overflow failed (1) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "123456789E9223372036854775807", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check overflow failed (2) with:\n s='%s'\n x=", s);
      mpfr_dump (x);
#if defined(__GNUC__)
      printf ("This failure is triggered by GCC bug 86554:\n"
              "  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86554\n"
              "  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87276 "
              "(about this test)\nWorkaround: disable code hoisting "
              "with -fno-code-hoisting in CFLAGS.\n");
      /* Note: In Debian, this error is obtained with gcc-snapshot from
         20180908-1 to 20181127-1. With gcc-snapshot from 20181209-1 to
         20190102-1 (at least), the MPFR build no longer seems affected
         in general, but using --with-gmp-build=... together with
         --enable-assert still triggers this failure. This bug has been
         fixed in the GCC trunk rev 267725, thus the future gcc-snapshot
         versions should no longer have this bug. */
#endif
      exit (1);
    }
  mpfr_strtofr (x, "123456789E170141183460469231731687303715884105728",
                &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check overflow failed (3) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }

  /* Limit overflow */
  mpfr_strtofr (x, "12E2147483646", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check overflow failed (4) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "12E2147483645", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (5) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "0123456789ABCDEF@2147483640", &s, 16, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (6) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "0123456789ABCDEF@540000000", &s, 16, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (7) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "1@2305843009213693951", &s, 16, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (8) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "1@2305843009213693951", &s, 17, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_INF (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (9) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }

  /* Check underflow */
  mpfr_strtofr (x, "123456789E-2147483646", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_ZERO (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check underflow failed (1) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "123456789E-9223372036854775807", &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_ZERO (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check underflow failed (2) with:\n s='%s'\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "-123456789E-170141183460469231731687303715884105728",
                &s, 0, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_ZERO (x) || !MPFR_IS_NEG (x) )
    {
      printf ("Check underflow failed (3) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "0123456789ABCDEF@-540000000", &s, 16, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_ZERO (x) || !MPFR_IS_POS (x))
    {
      printf ("Check overflow failed (7) with:\n s=%s\n x=", s);
      mpfr_dump (x);
      exit (1);
    }
  mpfr_strtofr (x, "1@-2305843009213693952", &s, 16, MPFR_RNDN);
  if (s[0] != 0 || !MPFR_IS_ZERO (x) || !MPFR_IS_POS (x) )
    {
      printf ("Check underflow failed (8) with:\n s='%s'\n x=", s);
      mpfr_dump (x);
      exit (1);
    }

  mpfr_clear (x);
}

static void
check_retval (void)
{
  mpfr_t x;
  int res;

  mpfr_init2 (x, 10);

  res = mpfr_strtofr (x, "01011000111", NULL, 2, MPFR_RNDN);
  MPFR_ASSERTN (res == 0);
  res = mpfr_strtofr (x, "11011000111", NULL, 2, MPFR_RNDN);
  MPFR_ASSERTN (res > 0);
  res = mpfr_strtofr (x, "110110001101", NULL, 2, MPFR_RNDN);
  MPFR_ASSERTN (res < 0);

  mpfr_clear (x);
}

/* Bug found by Christoph Lauter (in mpfr_set_str). */
static struct bug20081025_test {
  mpfr_rnd_t rnd;
  int inexact;
  const char *str;
  const char *binstr;
} Bug20081028Table[] = {
  {MPFR_RNDN, -1, "1.00000000000000000006", "1"},
  {MPFR_RNDZ, -1, "1.00000000000000000006", "1"},
  {MPFR_RNDU, +1, "1.00000000000000000006",
   "10000000000000000000000000000001e-31"},
  {MPFR_RNDD, -1, "1.00000000000000000006", "1"},


  {MPFR_RNDN, +1, "-1.00000000000000000006", "-1"},
  {MPFR_RNDZ, +1, "-1.00000000000000000006", "-1"},
  {MPFR_RNDU, +1, "-1.00000000000000000006", "-1"},
  {MPFR_RNDD, -1, "-1.00000000000000000006",
   "-10000000000000000000000000000001e-31"},

  {MPFR_RNDN, +1, "0.999999999999999999999999999999999999999999999", "1"},
  {MPFR_RNDZ, -1, "0.999999999999999999999999999999999999999999999",
   "11111111111111111111111111111111e-32"},
  {MPFR_RNDU, +1, "0.999999999999999999999999999999999999999999999", "1"},
  {MPFR_RNDD, -1, "0.999999999999999999999999999999999999999999999",
   "11111111111111111111111111111111e-32"},

  {MPFR_RNDN, -1, "-0.999999999999999999999999999999999999999999999", "-1"},
  {MPFR_RNDZ, +1, "-0.999999999999999999999999999999999999999999999",
   "-11111111111111111111111111111111e-32"},
  {MPFR_RNDU, +1, "-0.999999999999999999999999999999999999999999999",
   "-11111111111111111111111111111111e-32"},
  {MPFR_RNDD, -1, "-0.999999999999999999999999999999999999999999999", "-1"}
};

static void
bug20081028 (void)
{
  int i;
  int inexact, res;
  mpfr_rnd_t rnd;
  mpfr_t x, y;
  char *s;

  mpfr_init2 (x, 32);
  mpfr_init2 (y, 32);
  for (i = 0 ; i < numberof (Bug20081028Table) ; i++)
    {
      rnd     = Bug20081028Table[i].rnd;
      inexact = Bug20081028Table[i].inexact;
      mpfr_set_str_binary (x, Bug20081028Table[i].binstr);
      res = mpfr_strtofr (y, Bug20081028Table[i].str, &s, 10, rnd);
      if (s == NULL || *s != 0)
        {
          printf ("Error in Bug20081028: strtofr didn't parse entire input\n"
                  "for (i=%d) Str=\"%s\"", i, Bug20081028Table[i].str);
          exit (1);
        }
      if (! SAME_SIGN (res, inexact))
        {
          printf ("Error in Bug20081028: expected %s ternary value, "
                  "got %d\nfor (i=%d) Rnd=%s Str=\"%s\"\n Set binary gives: ",
                  inexact > 0 ? "positive" : "negative",
                  res, i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str);
          mpfr_dump (x);
          printf (" strtofr    gives: ");
          mpfr_dump (y);
          exit (1);
        }
      if (mpfr_cmp (x, y))
        {
          printf ("Error in Bug20081028: Results differ between strtofr and "
                  "set_binary\nfor (i=%d) Rnd=%s Str=\"%s\"\n"
                  " Set binary gives: ",
                  i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str);
          mpfr_dump (x);
          printf (" strtofr    gives: ");
          mpfr_dump (y);
          exit (1);
        }
    }
  mpfr_clear (y);
  mpfr_clear (x);
}

/* check that 1.23e is correctly parsed, cf
   https://gmplib.org/list-archives/gmp-bugs/2010-March/001898.html */
static void
test20100310 (void)
{
  mpfr_t x, y;
  char str[] = "1.23e", *endptr;

  mpfr_init2 (x, 53);
  mpfr_init2 (y, 53);
  mpfr_strtofr (x, str, &endptr, 10, MPFR_RNDN);
  mpfr_strtofr (y, "1.23", NULL, 10, MPFR_RNDN);
  if (mpfr_cmp (x, y) != 0)
    {
      printf ("x <> y in test20100310\n");
      exit (1);
    }
  if (endptr != str + 4) /* strtofr should take into account '1.23',
                            not '1.23e' */
    {
      printf ("endptr <> str + 4 in test20100310\n");
      exit (1);
    }
  mpfr_clear (x);
  mpfr_clear (y);
}

/* From a bug reported by Joseph S. Myers
   https://sympa.inria.fr/sympa/arc/mpfr/2012-08/msg00005.html */
static void
bug20120814 (void)
{
  mpfr_exp_t emin = -30, e;
  mpfr_t x, y;
  int r;
  char s[64], *p;

  mpfr_init2 (x, 2);
  mpfr_set_ui_2exp (x, 3, emin - 2, MPFR_RNDN);
  mpfr_get_str (s + 1, &e, 10, 19, x, MPFR_RNDD);
  s[0] = s[1];
  s[1] = '.';
  for (p = s; *p != 0; p++) ;
  *p = 'e';
  sprintf (p + 1, "%d", (int) e - 1);

  mpfr_init2 (y, 4);
  r = mpfr_strtofr (y, s, NULL, 0, MPFR_RNDN);
  if (r <= 0 || ! mpfr_equal_p (x, y))
    {
      printf ("Error in bug20120814\n");
      printf ("mpfr_strtofr failed on string \"%s\"\n", s);
      printf ("Expected inex > 0 and y = 0.1100E%d\n", (int) emin);
      printf ("Got inex = %-6d and y = ", r);
      mpfr_dump (y);
      exit (1);
    }

  mpfr_clear (x);
  mpfr_clear (y);
}

static void
bug20120829 (void)
{
  mpfr_t x1, x2, e;
  int inex1, inex2, i, r;
  char s[48] = "1e-1";

  mpfr_init2 (e, 128);
  mpfr_inits2 (4, x1, x2, (mpfr_ptr) 0);

  inex1 = mpfr_set_si (e, -1, MPFR_RNDN);
  MPFR_ASSERTN (inex1 == 0);

  for (i = 1; i <= sizeof(s) - 5; i++)
    {
      s[3+i] = '0';
      s[4+i] = 0;
      inex1 = mpfr_mul_ui (e, e, 10, MPFR_RNDN);
      MPFR_ASSERTN (inex1 == 0);
      RND_LOOP_NO_RNDF (r)
        {
          mpfr_rnd_t rnd = (mpfr_rnd_t) r;

          inex1 = mpfr_exp10 (x1, e, rnd);
          inex1 = VSIGN (inex1);
          inex2 = mpfr_strtofr (x2, s, NULL, 0, rnd);
          inex2 = VSIGN (inex2);
          /* On 32-bit machines, for i = 7, r8389, r8391 and r8394 do:
             strtofr.c:...: MPFR assertion failed: cy == 0
             r8396 is OK.
             On 64-bit machines, for i = 15,
             r8389 does: strtofr.c:678: MPFR assertion failed: err < (64 - 0)
             r8391 does: strtofr.c:680: MPFR assertion failed: h < ysize
             r8394 and r8396 are OK.
          */
          if (! mpfr_equal_p (x1, x2) || inex1 != inex2)
            {
              printf ("Error in bug20120829 for i = %d, rnd = %s\n",
                      i, mpfr_print_rnd_mode (rnd));
              printf ("Expected inex = %d, x = ", inex1);
              mpfr_dump (x1);
              printf ("Got      inex = %d, x = ", inex2);
              mpfr_dump (x2);
              exit (1);
            }
        }
    }

  mpfr_clears (e, x1, x2, (mpfr_ptr) 0);
}

/* https://sympa.inria.fr/sympa/arc/mpfr/2016-12/msg00043.html
   mpfr_strtofr can return an incorrect ternary value.
   Note: As a consequence, the value can also be incorrect if the current
   exponent range is not the maximum one (since the ternary value is used
   to resolve double rounding in mpfr_check_range); this can happen only
   if the value is a midpoint between 0 and the minimum positive number
   or the opposite. */
static void
bug20161217 (void)
{
  mpfr_t fp, z;
  static const char * num = "0.1387778780781445675529539585113525390625e31";
  /* The above number is 5^47/2^9. */
  int inex;

  mpfr_init2 (fp, 110);
  mpfr_init2 (z, 110);

  inex = mpfr_strtofr (fp, num, NULL, 10, MPFR_RNDN);
  MPFR_ASSERTN(inex == 0);
  mpfr_set_str_binary (z, "10001100001000010011110110011101101001010000001011011110010001010100010100100110111101000010001011001100001101E-9");
  MPFR_ASSERTN(mpfr_equal_p (fp, z));

  /* try with 109 bits */
  mpfr_set_prec (fp, 109);
  inex = mpfr_strtofr (fp, num, NULL, 10, MPFR_RNDN);
  MPFR_ASSERTN(inex < 0);
  mpfr_set_str_binary (z, "10001100001000010011110110011101101001010000001011011110010001010100010100100110111101000010001011001100001100E-9");
  MPFR_ASSERTN(mpfr_equal_p (fp, z));

  mpfr_clear (fp);
  mpfr_clear (z);
}

/* check bug in MPFR 3.1.5 is fixed: cf
   https://sympa.inria.fr/sympa/arc/mpfr/2017-03/msg00009.html
   Note: same bug as bug20161217. See also the comments of bug20161217;
   here, this is a case where the value is incorrect. */
static void
bug20170308 (void)
{
  mpfr_exp_t emin;
   /* the following is slightly larger than 2^-1075, thus should be rounded
      to 0.5*2^-1074, with ternary value < 0 */
  char str[] = "2.47032822920623272089E-324";
  mpfr_t z;
  int inex;

  emin = mpfr_get_emin ();
  mpfr_init2 (z, 53);
  set_emin (-1073);
  /* with emin = -1073, the smallest positive number is 0.5*2^emin = 2^(-1074),
     thus str should be rounded to 2^(-1074) with inex > 0 */
  inex = mpfr_strtofr (z, str, NULL, 10, MPFR_RNDN);
  MPFR_ASSERTN(inex > 0 && mpfr_cmp_ui_2exp (z, 1, -1074) == 0);
  set_emin (-1074);
  /* with emin = -1074, str should be rounded to 2^(-1075) with inex < 0 */
  inex = mpfr_strtofr (z, str, NULL, 10, MPFR_RNDN);
  MPFR_ASSERTN(inex < 0 && mpfr_cmp_ui_2exp (z, 1, -1075) == 0);
  mpfr_clear (z);
  set_emin (emin);
}

/* r13299 fails with 8-bit limbs (micro-gmp/8). */
static void
bug20181127 (void)
{
  char s[] = "9.Z6nrLVSMG1bDcCF2ONJdX@-183295525";  /* base 58 */
  mpfr_t x, y;

  mpfr_inits2 (6, x, y, (mpfr_ptr) 0);
  mpfr_set_ui_2exp (x, 5, -1073741701, MPFR_RNDN);
  mpfr_strtofr (y, s, NULL, 58, MPFR_RNDZ);
  if (! mpfr_equal_p (x, y))
    {
      printf ("Error in bug20181127 on %s (base 58)\n", s);
      printf ("Expected x = ");
      mpfr_dump (x);
      printf ("Got      y = ");
      mpfr_dump (y);
      printf ("*Note* In base 58, x ~= ");
      mpfr_out_str (stdout, 58, 8, x, MPFR_RNDN);
      printf ("\n");
      exit (1);
    }
  mpfr_clears (x, y, (mpfr_ptr) 0);
}

static void
coverage (void)
{
#if _MPFR_EXP_FORMAT >= 3 && _MPFR_PREC_FORMAT == 3 && MPFR_PREC_BITS == 64
  char str3[] = "1@-2112009130072406892";
  char str31[] = "1@-511170973314085831";
  mpfr_t x;
  int inex;
  mpfr_exp_t emin;

  /* exercise assertion cy == 0 around line 698 of strtofr.c */
  emin = mpfr_get_emin ();
  set_emin (mpfr_get_emin_min ());
  /* emin = -4611686018427387903 on a 64-bit machine */
  mpfr_init2 (x, 1);
  inex = mpfr_strtofr (x, str3, NULL, 3, MPFR_RNDN);
  /* 3^-2112009130072406892 is slightly larger than (2^64)^-52303988630398057
     thus we should get inex < 0 */
  MPFR_ASSERTN(inex < 0);
  MPFR_ASSERTN(mpfr_cmp_ui_2exp (x, 1, -52303988630398057 * 64) == 0);
  inex = mpfr_strtofr (x, str31, NULL, 31, MPFR_RNDN);
  /* 31^-511170973314085831 is slightly smaller than (2^64)^-39569396093273623
     thus we should get inex > 0 */
  MPFR_ASSERTN(inex > 0);
  MPFR_ASSERTN(mpfr_cmp_ui_2exp (x, 1, -39569396093273623 * 64) == 0);
  mpfr_clear (x);
  set_emin (emin);
#endif
}

#define BSIZE 512

static void
random_tests (void)
{
  char s0[BSIZE], s1[BSIZE], s2[BSIZE+64];
  mpfr_t x0, x1, x2;
  int prec, i;

  for (prec = MPFR_PREC_MIN; prec < 300; prec++)
    {
      mpfr_inits2 (prec, x0, x1, x2, (mpfr_ptr) 0);

      for (i = 0; i < 20; i++)
        {
          const char *num_to_text;
          mpfr_exp_t e0, e1;
          int base, j, k, neg;
          int noteq = 0;
          char d;

          /* We want the same exponent for x0 and its successor x1.
             This is not possible for precision 1 in base 2. */
          do
            base = 2 + (randlimb () % 61);
          while (prec == 1 && base == 2);

          num_to_text = base <= 36 ? num_to_text36 : num_to_text62;

          do
            {
              /* Let's consider only positive numbers. We should test
                 negative numbers, but they should be built later, just
                 for the test itself. */
              tests_default_random (x0, 0,
                                    mpfr_get_emin (), mpfr_get_emax (), 1);
              mpfr_set (x1, x0, MPFR_RNDN);
              mpfr_nextabove (x1);
              mpfr_get_str (s0, &e0, base, BSIZE - 1, x0, MPFR_RNDU);
              mpfr_get_str (s1, &e1, base, BSIZE - 1, x1, MPFR_RNDD);
            }
          while (! (mpfr_regular_p (x0) && mpfr_regular_p (x1) && e0 == e1));

          /* 0 < x0 <= (s0,e) <= (s1,e) <= x1 with e = e0 = e1.
             Let's build a string s2 randomly formed by:
             - the common prefix of s0 and s1;
             - some of the following digits of s0 (possibly none);
             - the next digit of s0 + 1;
             - some of the following digits of s1 (possibly none).
             Then 0 < x0 <= (s0,e) < (s2,e) <= (s1,e) <= x1, and with
             a very high probability that (s2,e) < (s1,e); noteq is
             set to true in this case.
             For instance, if:
               s0 = 123456789
               s1 = 124012345
             one can have, e.g.:
               s2 = 12345734
               s2 = 123556789
               s2 = 124
               s2 = 124012
             s2 is not taken completely randomly between s0 and s1, but it
             will be built rather easily, and with the randomness of x0,
             we should cover all cases, with s2 very close to s0, s2 very
             close to s1, or not too close to either. */

          neg = randlimb () & 1;
          s2[0] = neg ? '-' : '+';
          s2[1] = '.';

          for (j = 0;
               MPFR_ASSERTN (s0[j] != 0 && s1[j] != 0), s0[j] == s1[j];
               j++)
            s2[j+2] = s0[j];

          /* k is the position of the first differing digit. */
          k = j;

          while (j < BSIZE - 2 && randlimb () % 8 != 0)
            {
              MPFR_ASSERTN (s0[j] != 0);
              s2[j+2] = s0[j];
              j++;
            }

          MPFR_ASSERTN (s0[j] != 0);
          /* We will increment the next digit. Thus while s0[j] is the
             maximum digit, go back until this is no longer the case
             (the first digit after the common prefix cannot be the
             maximum digit, so that we will stop early enough). */
          while ((d = s0[j]) == num_to_text[base - 1])
            j--;
          noteq = j != k;
          s2[j+2] = d = *(strchr (num_to_text, d) + 1);
          if (d != s1[j])
            noteq = 1;
          j++;

          while (j < BSIZE - 1 && randlimb () % 8 != 0)
            {
              MPFR_ASSERTN (s1[j] != 0);
              s2[j+2] = s1[j];
              j++;
            }

          sprintf (s2 + (j+2), "@%" MPFR_EXP_FSPEC "d", (mpfr_eexp_t) e0);

          while (noteq == 0 && j < BSIZE - 1)
            {
              if (s1[j] != '0')
                noteq = 1;
              j++;
            }

          if (neg)
            {
              mpfr_neg (x0, x0, MPFR_RNDN);
              mpfr_neg (x1, x1, MPFR_RNDN);
            }

          if (noteq)
            {
              mpfr_strtofr (x2, s2, NULL, base, MPFR_RNDZ);
              if (! mpfr_equal_p (x2, x0))
                {
                  printf ("Error in random_tests for prec=%d i=%d base=%d\n",
                          prec, i, base);
                  printf ("s0 = %s\ns1 = %s\ns2 = %s\n", s0, s1, s2);
                  printf ("x0 = ");
                  mpfr_dump (x0);
                  printf ("x2 = ");
                  mpfr_dump (x2);
                  exit (1);
                }
            }

          mpfr_strtofr (x2, s2, NULL, base, MPFR_RNDA);
          if (! mpfr_equal_p (x2, x1))
            {
              printf ("Error in random_tests for prec=%d i=%d base=%d\n",
                      prec, i, base);
              printf ("s0 = %s\ns1 = %s\ns2 = %s\n", s0, s1, s2);
              printf ("x1 = ");
              mpfr_dump (x1);
              printf ("x2 = ");
              mpfr_dump (x2);
              exit (1);
            }
        }
      mpfr_clears (x0, x1, x2, (mpfr_ptr) 0);
    }
}

int
main (int argc, char *argv[])
{
  tests_start_mpfr ();

  coverage ();
  check_special();
  check_reftable ();
  check_parse ();
  check_overflow ();
  check_retval ();
  bug20081028 ();
  test20100310 ();
  bug20120814 ();
  bug20120829 ();
  bug20161217 ();
  bug20170308 ();
  bug20181127 ();
  random_tests ();

  tests_end_mpfr ();
  return 0;
}
